/**
 * TDS PEC 4
 * Grupo 3H2M
 *
 * El paquete <code>edu.uoc.tds.pec4.server.bbdd</code> agrupa todos los
 * interfaces y clases que encapsulan los objetos de acceso a datos (DAO),para
 * realizar el acceso a datos. La base de datos es PostgreSQL.<br />
 * También incluyen la implementación del patrón Factory y Abstract Factory.<br />
 *
 */
package edu.uoc.tds.pec4.server.bbdd;

import edu.uoc.tds.pec4.server.bbdd.exceptions.DAOFactoryException;
import edu.uoc.tds.pec4.server.bbdd.exceptions.DataBaseDAOException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException; 
import java.util.Properties;

/**
 * La clase <code>DAOFactory</code> es la factoría abstracta encargada de
 * instanciar a la factoría de objetos DAO que corresponda.<br />
 * Para ello utiliza el fichero properties, dependiendo de la cadena que aparezca
 * en la url de conexión, así podrá instanciar una factoría u otra.<br />
 * Por ejemplo, en el caso que nos ocupa tenemos ya implementada una factoría
 * para Postgres, si el fichero de propiedades posee la cadena 'postgres' entonces
 * la clase abstracta instanciará la factoría PostgresDAOFactory.<br />
 * Si en el futuro el acceso a datos se amplía a otros gestores, como Oracle,
 * bastaría sólo con implementar una factoría para Oracle.<br />
 * La ventaja de utilizar el patrón Factory, en este caso es que la aplicación
 * no tiene por qué saber nada sobre el origen de datos subyacente. <br />
 * Si se toma la decisión de cambiar la base de datos de Postgres a Microsoft
 * SQL Server, se crea una nueva clase SQLServerDAOFactory y el Factory
 * instanciará la clase correspondiente al leer el archivo de propiedades.<br />
 *
 * @author	Luis Rodríguez-Manzaneque Sánchez
 * @version	21/11/2011
 * @since	1.00
 * @see         edu.uoc.tds.pec4.server.bbdd.exceptions.DAOFactoryException
 */
public abstract class DAOFactory {

    /** propertiesFile Fichero de configuración, con su ruta absoluta. */
    private static final String propertiesFile = "properties/configuration.properties";

    // true=Carga de Properties desde archivo
    private static boolean propiedadesCargadas = false;
    private static String sUrl = null;

    // Existirá un método por cada DAO que puede ser creado.
    // Las factorías concretas tendrán que implementar
    // esos métodos.
    public abstract IUsuarioDAO getUsuarioDAO() throws DataBaseDAOException;

    public abstract IMaestrosDAO getMaestrosDAO() throws DataBaseDAOException;
    
    public abstract IAulaDAO getAulaDAO() throws DataBaseDAOException;
    
    public abstract IEquipamientoDAO getEquipamientoDAO() throws DataBaseDAOException;
    
    public abstract IAuditoriaDAO getAuditoriaDAO() throws DataBaseDAOException;
    
    public abstract ISolicitudDAO getSolicitudDAO() throws DataBaseDAOException;

    public abstract IReservaDAO getReservaDAO() throws DataBaseDAOException;
    
    public abstract IRankingDAO getRankingDAO() throws DataBaseDAOException;
    
    public abstract IRentabilidadDAO getRentabilidadDAO() throws DataBaseDAOException;
    /**
     * Método estático para la creación de la instancia adecuada del Factory.
     * Devuelve un objeto que implementa DAOFactory adecuado al acceso a datos. <br />
     *
     * @throws  DAOFactoryException En caso de producirse un error al leer el
     *          archivo de propiedades
     */
    public static DAOFactory getDAOFactory() throws DAOFactoryException {
        try {
            // Carga de propiedades desde archivo
            if (!propiedadesCargadas) {
                Properties objProperties = new Properties();
                FileInputStream objFile = new FileInputStream(propertiesFile);
                objProperties.load(objFile);
                propiedadesCargadas = true;
                sUrl = objProperties.getProperty("url");
            }

            if (sUrl.indexOf("postgresql")>0) {
                return new PostgresDAOFactory();
            } else {
                return null;
            }
        } catch (FileNotFoundException eFnfe) {
            // Error: El fichero no se ha encontrado
            throw new DAOFactoryException(DAOFactoryException.FILE_PROP_CAN_NOT_READ,eFnfe);
        } catch (IOException eIo) {
            // Error de lectura
            throw new DAOFactoryException(DAOFactoryException.FILE_PROP_CAN_NOT_READ,eIo);
        } catch (Exception eV) {
            // Error desconocido
            throw new DAOFactoryException(DAOFactoryException.FILE_PROP_CAN_NOT_READ,eV);
        }
    }
}
